;›;*************************************›;›; ULD: UPLOAD PROGRAM DATA TO DUP BOARD›;›; ENTRY:STRADR SET BY SET ADDRESS›; :COMMAND›;›; EXIT:STATUS ($A0) HOLDS STATUS›; :0=OK 1=CHECKSUM ERROR›; :2=MEMORY OUT OF RANGE ERROR›;›;**************************************›;›ULDPROC›;›:STATUS=$A0;STATUS OF OPERATION›:TEMP=$AF;TEMP MEMORY LOCATION›;›LDA#$00›STA:TEMP›LDASTRADR+1›CMP#$60;TOP OF MEMORY EXCEDED?›BCC:ULD01;YES WE HAVE MEM ERROR›LDA#$FF›STA:TEMP›:ULD01LDA#0;SAVE VALUE OF LENTH›LDXSTRADR;LOW BYTE OF POINTER›STXBPNT›LDXSTRADR+1›STXBPNT+1›JSRREAD›LDA:TEMP›BNE:ULD02›INCSTRADR+1;ADD ONE TO UPLOAD ADR›BNE:ULDXT›:ULD02LDA#$02›STA:STATUS›:ULDXTRTS›EPROC›;›;*************************************›;›; DSKSTS: CHECK DISK STATUS›;›; ENTRY:NONE›; EXIT:$A0=0 IF OK›; :$A0=1 IF DOOR OPEN OR WRITE›; : PROTECT IS ON›; : SETS BIT 3 IN STAT›;›;**************************************›;›DSKSTSPROC›;›:STATUS=$A0›;›LDA#0›STA:STATUS›LDASTREG›STATEMP›BITTEMP›BPL:DSK01;DOOR IS NOT OPEN›LDA:STATUS›ORA#$01›STA:STATUS›:DSK01LDASTAT›AND#$08;WRITE PROTECT NOT ON›BEQ:DSK02›LDA:STATUS›ORA#$01›STA:STATUS›;›;NOW SET GLOBAL STATUS BITS UP›;›:DSK02LDATEMP›EOR#$FF›STASTAT+1›RTS›;›;›;*************************************›;›; DENSITY AND A HALF FORMAT ROUTINE›;›;*************************************›;›DAHFPROC›;›:STATUS=$A0›:TRYS=$AF›;›;IF WE GET HERE FORCE DENSITY AND 1/2›;›LDA#0›STANTRK›JSRSKTK;GO TO TRACK ZERO›;›LDA#26›STACONFIG+3›LDA#128›STACONFIG+7›LDA#0›STACONFIG+5›STACONFIG+6›LDASTAT›AND#%01011111›ORA#%10000000;SET DUAL DENS STATUS›STASTAT›JSRDFLTS;SET DEFAULT SECTOR SKEW›LDA#0;START WITH TRACK 0›JSRDUTRK;MAKE A HALF DENS TRACK›LDA#$DF;PUT FDC INTO DD MODE›ANDDRA›STADRA›:LOOPJSRDFMT;FORMAT TRACK›LDA:STATUS›BNE:DH001;ERROR IN FORMAT›LDA#39›CMPTRACK›BEQ:DH002;END OF FORMAT›JSRINT›JMP:LOOP›;›:DH002LDA#0›STA:STATUS›JMP:EXIT›;›:DH001LDA#$01;HANDLE THE ERROR›STA:STATUS›;›:EXITRTS›EPROC›;›;**************************************›;›; DOUBLE DENSITY FORMAT›;›;**************************************›;›DDFMTPROC›;›:STATUS=$A0›;›LDA#$DF;PUT IN DD MODE›ANDDRA›STADRA›LDA#0›JSRDDTRK;INIT TRACK 0›JSRDFMT;FORMAT TRACK›LDA:STATUS;CHECK STATUS›BNE:SFR01;ERROR›LDA#1›JSRDDTRK;INIT REGULAR TRACK›JSRINT;INCREMET TRACK NUMBER›:LOOP1JSRDFMT;FORMAT TRACK›LDA:STATUS›BNE:SFR01;ERROR›LDA#39›CMPTRACK›BEQ:SFR02;DONE›JSRINT;INCREMENT TRACK NUMBER›JMP:LOOP1›:SFR02LDA#0›STA:STATUS›JMP:EXIT›;›;HANDLE AN ERROR›;›:SFR01LDA#$01›STA:STATUS›:EXITRTS›EPROC›;›;*************************************›;SINGLE DENSITY FD FORMAT›;›;*************************************›;›SFRMATPROC›;›:STATUS=$A0;STATUS LOCATION›;›LDA#$20;PUT INTO SD MODE›ORADRA›STADRA›JSRITRKS;MAKE SINGLE D TRACK IMAGE›:LOOPJSRFMT;FORMAT TRACK›LDA:STATUS›BEQTRKOK›LDA#$01›STA:STATUS›JMP:EXIT›;›TRKOKLDA#39›CMPTRACK›BEQ:SDF01›JSRINT;INCREMENT TRACK NUMBER›JMP:LOOP›;›:SDF01LDA#$00›STA:STATUS›;›;SET UP SKEW TABLE›;›:EXITRTS›EPROC›;›;**************************************›;›;INCREMENT TRACK NUMBER›;›;**************************************›;›INTPROC›;›:EOTKP=$AD›;›LDACONFIG+3;SECTOR LENTH›ASLA;* 2›STA:EOTKP›LDA#$FF›JSRSTEPT;GO TO NEXT TRACK›JSRFINT›LDX#$00›LDATRACK;GET TRACK NUMBER›LTRKSTA(TNPNT,X)›INX›INX›CPX:EOTKP;ALL TRACK NUMBERS UPDATED?›BNELTRK›RTS›EPROC›;›;**************************************›;›; FMT: FORMAT SINGLE TRACK SD›;›;**************************************›;›FMTPROC›;›:STATUS=$A0;STATUS OF FORMAT›:TRYS=$AF;NUMBER OF RETRYS›;›LDA#$05›STA:TRYS;SET NUMBER OF RETRYS›;›:FMT09JSRDSKSTS;CHECK STATUS OF DISK›LDA:STATUS›BEQ:FMT01›JMP:EXIT;DEVICE NOT READY EXIT›:FMT01LDA#$00›STABASE;RESET LOW BYTE OF POINTER›LDA#$20›STABASE+1;RESET HIGH BYTE›LDY#0;CLEAR INDEX›STYDTAREG;INIT DATA REG›LDA#1›STAWT24E›;›LDX#100›:FMT02DEX;HOLD YOUR HORSES A BIT›BNE:FMT02;JUST HUMOR ME, OK!›;›LDA#$F0;WRITE TRACK CMD›STACMDREG›:FMT03BITDRA›BPL:FMT03›STYDTAREG›:FMT04BITDRA›BPL:FMT04›STYDTAREG›LDAWT64D›LDA#$D1›STAWT24E;RESET TIMER TO 208 MS›;›:FMT05BITDRA›BMI:FMT25›BVS:FMT05›BVCTRKERR;RETRY TRACK WRITE›BPL:FMT05›:FMT25LDA(BASE),Y›STADTAREG;NEXT DATA›INCBASE;INCREMENT BASE POINTER›BNE:FMT15›INCBASE+1›:FMT15LDABASE›CMPBPNT›BNE:FMT05›LDABPNT+1›CMPBASE+1›BNE:FMT05›LDA#$01;MASK FOR BUSY›LDX#0;DATA BYTE›:FMT06ANDSTREG;BUSY STATUS?›BEQ:FMT07;CMD GONE›BITDRA›BPL:FMT06;WAIT FOR DATA REQUEST›STXDTAREG;PADDING›JMP:FMT06›:FMT07LDASTREG›AND#$04;LOST DATA?›BEQ:FMTXT;GOOD TRACK›TRKERRLDAWT64D›JSRFINT;RETRY TRACK FORMAT›DEC:TRYS›BNE:FMT08›LDA#$01›STA:STATUS›JMP:EXIT›:FMT08JMP:FMT09›:FMTXTLDA#$00›STA:STATUS›:EXITLDARTDE;CLEAR TIMING PULSE›RTS›EPROC›;›;**************************************›;›; DFMT: FORMAT SINGLE TRACK DD›;›;**************************************›;›DFMTPROC›;›:STATUS=$A0;STATUS OF FORMAT›:TRYS=$AF;NUMBER OF RETRYS›;›LDA#$05›STA:TRYS;SET NUMBER OF RETRYS›;›:FMT09JSRDSKSTS;CHECK DISK STATUS›LDA:STATUS›BEQ:FMT01›JMP:EXIT;DEVICE NOT READY EXIT›:FMT01LDA#$00›STABASE;RESET LOW BYTE OF POINTER›LDA#$20›STABASE+1;RESET HIGH BYTE›LDY#$4E;CLEAR INDEX›STYDTAREG;INIT DATA REG›LDA#1›STAWT24E›;›LDX#100›:FMT02DEX;HOLD YOUR HORSES A BIT›BNE:FMT02;JUST HUMOR ME, OK!›;›LDA#$F0;WRITE TRACK CMD›STACMDREG›:FMT03BITDRA›BPL:FMT03›STYDTAREG›:FMT04BITDRA›BPL:FMT04›STYDTAREG›LDAWT64D›LDA#$CC›STAWT24E;RESET TIMER TO 208 MS›LDY#0›LDA(BASE),Y›;›:FMT05BITDRA;4›BVC:TRKER;2+ ERROR TRY AGAIN›BPL:FMT05;2+›STADTAREG;4 NEXT DATA›INCBASE;5 INCREMENT BASE POINTER›BNE:FMT15;2 +›INCBASE+1;5›:FMT15LDA(BASE),Y;5+›CMP#$B7;2 END OF TRACK MARK›BNE:FMT05;3›LDA#$01;MASK FOR BUSY›LDX#$4E;DATA BYTE›:FMT06ANDSTREG;BUSY STATUS?›BEQ:FMT07;CMD GONE›BITDRA›BPL:FMT06;WAIT FOR DATA REQUEST›STXDTAREG;PADDING›JMP:FMT06›:FMT07LDASTREG›AND#$04;LOST DATA?›BEQ:FMTXT;GOOD TRACK›:TRKERLDAWT64D›JSRFINT;RETRY TRACK FORMAT›DEC:TRYS›BNE:FMT08›LDA#$01›STA:STATUS›JMP:EXIT›:FMT08JMP:FMT09›:FMTXTLDA#$00›STA:STATUS›:EXITLDARTDE;CLEAR TIMING PULSE›RTS›EPROC›;›;›;**************************************›;›; FORCE INTERRUPT›;›;**************************************›;›FINTPHA›TXA›PHA›LDA#$D0›STACMDREG›LDX#7›FINT1DEX›BNEFINT1›LDA#1›FINT2BITSTREG›BNEFINT2›PLA›TAX›PLA›RTS›;›;**************************************›;›; VDSK: VERIFY DISK›;›; ENTRY:ACC=DATA TO COMMPARE›; EXIT:STATUS=0 VERIFY GOOD›; :STATUS=0 BAD DISK›;›;**************************************›;›VDSKPROC›;›:STATUS=$A0›:DATA=$A1›;›STA:DATA;SAVE COMPARE DATA FOR LATER›;›LDA#39;TRACK 39›STANTRK›LDA#0›STABPNT1;BUFFER FOR BAD SECTOR MAP›LDA#$20›STABPNT1+1›LDA#$FF›STABUFF›STABUFF+1›:DH003JSRSKTK›LDA:DATA;DATA TO COMPARE›JSRVTRK›LDA:STATUS›BEQ:DH001;NO SECTOR ERROR›JMP:VDXIT;BAD SECTOR ERROR, EXIT›:DH001DECNTRK›BITNTRK;LESS THAN ZERO?›BPL:DH003›LDA#0›STA:STATUS›:VDXITRTS›EPROC›;›;**************************************›;›; VTRK : VERIFY THAT A TRACK IS WRITTEN›; CORRECTLY›;›; ENTRY: A = DATA TO COMPARE›; NTRK = TRACK #›; BPNT1 = PNTR TO SECTOR INFO›; EXIT: BPNT1 POINTS TO BAD SECR INFO›;›;**************************************›;›VTRKPROC›;›:STATUS=$A0›;›PHA;SAVE DATA TO COMPARE›LDA#0›STA:STATUS›STABPNT;PNTR TO MODEL SECTOR›LDA#$21›STABPNT+1›PLA›LDY#0›VT1STA(BPNT),Y›INY›BNEVT1›LDA#0;SET INDEX TO SECTOR›STASECT›VT2LDXSECT›LDASKTAB,X;GET SECTOR NUMBER›JSRCTS;CHECK TRACK SECTOR STATUS›JSRVSEC›BCCVT3›LDA#$01›STA:STATUS›JMP:VTXIT;BAD SECTOR ERROR, EXIT NOW›VT3INCSECT›LDXCONFIG+3;END OF TRACK?›CPXSECT›BNEVT2›:VTXITRTS›EPROC›;›;›;**************************************›;›; MULT : 8 BIT MULTIPLY›;›; ENTRY : ACC = MULTIPLIER›; X-REG = MULTIPLICAND›; EXIT : PROD IN ACC AND X REG›;›;**************************************››MULTPROC›;›:MCAND=$82›:MLPLR=$84›:PROD=$86›;›STA:MLPLR›STX:MCAND›LDA#0›STA:PROD+1›LDX#8›SHIFTASLA›ROL:PROD+1›ASL:MCAND›BCCCHCNT›CLC›ADC:MLPLR›BCCCHCNT›INC:PROD+1›CHCNTDEX›BNESHIFT›LDX:PROD+1;LSB IN ACC, MSB IN X›RTS›EPROC›;›;**************************************›;›; STEP TRACK›; THIS ROUTINE WILL STEP ONE TRACK›;›; ENTRY:ACC=DIRECTION›; :$00 = STEP FORWARD›; :$FF = STEP BACKWARD›;›; EXIT:CARRY SET STEP ERROR›; ;CARRY CLEAR OK›;**************************************›;›STEPTPHA;SAVE COMMAND›JSRTINC;INC TRACK COUNTER›BCSSTEPTX;EXIT IF ERROR›PLA›PHA›JSRSTEP›PLA›PHA›JSRSTEP›CLC›STEPTXPLA›RTS›;›;›;**************************************›;›; STEPPER MOTOR ROUTINE›; THIS ROUTINE ONLY STEPS A HALF A›; A TRACK›;›; ENTRY:ACC=STEP DIRECTION›; :$00=STEP FORWARD›; ;$FF=STEP BACKWARD›;›; EXIT:NONE›;›;**************************************›;›STEPPHA;SAVE COMMAND›LDADRB;GET CURRENT STEP POSITION›ORA#$C3;STRIP OFF OTHER BITS›LDX#$00;SET INDEX COUNT›STEP21CMPSDAT,X;FIND ENTRY IN TABLE›BEQSTEP22›INX;NEXT ENTRY›CPX#$05;ALL OUT OF ENTRIES›BNESTEP21›PLA›SEC;SET ERROR FLAG›BCSSTPXIT;EXIT FROM ROUTINE›;›STEP22PLA;GET COMMAND BACK›CMP#$00;COMPARE DIRECTION?›BNESTEP01;BACKWARD STEP›INX;POINT TO NEXT ENTRY›CPX#$05;IF XREG=5 THEN›BNESTEP23›LDX#$01;XREG=1›STEP23LDADRB;LOAD STEP DATA›ORA#$3C;SET ALL BITS HIGH›ANDSDAT,X;SET ONE BIT LOW›STADRB;SET PORT›JSRSWAIT;WAIT FOR 10mSEC›CLC;SET OK STATUS›BCCSTPXIT››STEP01DEX;POINT TO NEXT ENTRY›CPX#$00;IF XREG=0 THEN›BNESTEP23›LDX#$04;XREG = 4›BNESTEP23›STPXITRTS;EXIT POINT STEP›;›SDATDB$FF,$FB,$F7,$EF,$DF;STEP DATA›;›;**************************************›;›; TRACK INCREMENT ROUTINE›;›;**************************************›;›TINCPHA›CMP#0›BEQTINC01›INCTRACK›LDATRACK›CMP#40;FORTY TRACKS?›BCCTINCXT›LDA#39›STATRACK›SEC›BCSTINCXT›TINC01DECTRACK›LDATRACK›CMP#$FF›BNETINC02›LDA#$00›STATRACK›SEC›BCSTINCXT›TINC02CLC›TINCXTPLA›RTS›;›;›;**************************************›;›; READ DISK ADDRESS›; RETURNS ADDRESS IN SIX BYTE BLOCK›; ON PAGE ZERO›;›;**************************************›;›RADRPROC›;›:TRYS=$A1›;›PHA;SAVE ACC›TXA›PHA›LDA#$06›STA:TRYS;SET NUMBER OF TRYS AT READ›RADR10LDX#$7A›LDA#$D0›JSRSTMO›LDX#$00;INDEX OF BLOCK›LDA#$C0;LOAD READ ADRESS COMMAND›STACMDREG;›RADR01BITDRA;WATCH DATA READY FLAG›BVCRADR04›BPLRADR01›LDADTAREG;READ DATA REGISTER›STATADRES,X›LDAWT64D›INX›CPX#$06;SIX BYTES YET?›BNERADR01›LDA#$01›RADR03BITSTREG›BNERADR03›LDA#$08›BITSTREG›BEQRDRXIT;ALL SIX BYTES READ, EXIT›DEC:TRYS›BNERADR10›RADR05SEC;SET CARRY TO IND. ERROR›BCSRADRXT›;›RADR04LDARTDE;DISABLE INTERRUPTS›DEC:TRYS;DECREMENT # OF TRYS›BEQRADR05;ERROR, EXIT›LDA#$D0›JSRSTMO;SET TIME OUT›JMPRADR01›;›;SIX BYTES READ, EXIT›;›RDRXITCLC;NO ERROR›;›RADRXTPLA›TAX›PLA›RTS›EPROC›;›;**************************************›;›; SWAIT:10 MSEC DELAY LOOP›;›; VARIABLE SRATE NOW CONTAINS TIME›; TO WASTE DOING NOTHING›;›; :PRESERVES ALL REGISTERS›;›;**************************************›;›SWAITPHA;SAVE ACCUMULATOR›TXA›PHA;SAVE X REGISTER›;›;9 CYCLES›;›LDA#$00›STATEMP›;›;5 CYCLES›;›SWAIT1LDXSRATE;STEP TIME›SWAIT0DEX;DECREMENT X REG›DEX›INX›BNESWAIT0›;›;9 CYCLES * 111=999›;›INCTEMP›LDATEMP›CMP#$0A›BNESWAIT1›;›PLA;POP X REG›TAX›PLA;POP ACCUMULATOR›;›RTS›;›;›;**************************************›;›; SEEK TRACK ZERO›; PRESERVES ALL REGISTERS›; AND INITIALIZES DISK ADDRESS›;›;**************************************›;›TRK0PROC›;›PHA;SAVE ACCUM›TXA;PUSH X REG›PHA›TYA;PUSH Y REG›PHA›JSRFINT;FORCE INTERRUPT›LDA#$55›STATRKREG›STATRACK›TRK001LDA#$48›STACMDREG;STEP IN COMMAND›LDA#$00›JSRSTEP;STEP DRIVE›JSRSWAIT›:LOOPLDASTREG;WAIT FOR STEP NOT BUSY›AND#$01›BNE:LOOP›LDASTREG›AND#$04;CHECK FOR TRACK ZERO IND›BNETRK001;IF NOT TRK0 KEEP GOING›;›;OK, WE ARE WITHIN +/- 1/2 TRACK›;GIVE THE STEPPER THE COUP DE GRASS›;›LDADRB›ORA#%00111100›ANDSDAT + 4;STEPPER CAL POSITION›STADRB›JSRSWAIT›LDA#0›STATRACK›LDADRB›STASTPPOS›CLC›PLA›TAY›PLA›TAX›PLA›RTS›EPROC›;›;›;**************************************›;›; SEEK TRACK›;›; ENTRY:NTRK = TRACK NUMBER TO SEEK›;›; EXIT:CARRY SET IF TRACK NOT FOUND›;›;›;**************************************›;›SKTKPROC›;›:LOOPLDANTRK›CMPTRACK;NEW TRACK?›BEQ:SKT02;TRACK FOUND, EXIT OK›BCS:SKT01;NEW TRACK IS LESS›LDA#$00;STEP FORWARD›JSRSTEPT;STEP A TRACK›BCC:LOOP;IF NO ERROR, LOOP›BCSSKTXIT;ERROR IN STEPING›:SKT01LDA#$FF;STEP THE OTHER WAY›JSRSTEPT;STEP A TRACK›BCC:LOOP;IF OK, KEEP LOOPING›BCSSKTXIT;ERROR IN STEPPING›:SKT02CLC›SKTXITRTS›EPROC›;›;**************************************›;›; CALCULATE NEW TRACK/SECTOR NUMBER›;›; ENTRY:ATARI SECTOR NUMBER IN›; :CMDFRM+2 AND CMDFRM+3›; EXIT:TRACK NUMBER IN›; :NTRK AND SECTOR NUMBER›; :IN NSEC CMDFRM+2 AND +3 ARE›; :DESTROYED›;›; SAVES NO REGISTERS›;›;**************************************›;›NTSPROC›;›SEC;PREPARE TO SUBTRACT›LDACMDFRM+2›SBC#$01›STACMDFRM+2›LDACMDFRM+3›SBC#$00›STACMDFRM+3›BCCNTSERR;SECTOR NUMBER ERROR›;›;CALCULATE TRACK/SECTOR›;›ACCL=CMDFRM+2›ACCH=CMDFRM+3›;›BITSTAT;CHECK STATUS REGISTER›BMI:NTS01;DUAL DENSITY›LDA#18;NUMBER OF SECTORS PER TRACK›JMP:NTS02›;›:NTS01LDA#26;26 SECTORS PER TRACK›:NTS02STATEMP›LDY#8;NUMBER OF BITS TO DIVIDE BY›ASLACCL›UDIV1ROLACCH;SHIFT DIVIDEND›BCSUDIV2;JMP IF 1 SHFTD OUT OF DVDND›LDAACCH;SUBTRACT DIVISOR FROM ACCH›SEC›SBCTEMP›BCCUDIV4;JMP TO SHIFT AND COUNT IF›;UNDEFLOW IS IMMENIENT,CARRY›;IS QUOTIENT BIT›STAACCH;STORE DIFF IF NO UNDEFLOW›;FLAG IS QUOTIENT BIT›BCSUDIV4›;›UDIV2LDAACCH;SUBTRACT DVSR FRM ACCH;›SBCTEMP›BCSUDIV3;SKIP IF UNDERFLOW IMMENIENT›STAACCH›SEC›BCSUDIV4›UDIV3CLC;QUOTIENT BIT IS ZERO›UDIV4ROLACCL;SHIFT DIVIDENT LOW PART›DEY;COUNT INTERATIONS›BNEUDIV1›;›LDAACCL›STANTRK;STORE NEW TRACK NUMBER›LDAACCH›STANSEC;NEW SECTOR›INCNSEC;NSEC==+1›CLC›BCCNTSXIT›NTSERRSEC›NTSXITRTS›EPROC›;›LINKD2:DD15M4.ASM›